<template>
  <div class="query-list">
    <!-- 筛选面板 -->
    <el-card v-if="showQueryPanel" class="query-panel">
      <el-form
        class="query-form"
        size="small"
        label-suffix="："
        inline
      >
        <!-- 表单项插槽 -->
        <slot name="form" />

        <el-form-item>
          <!-- 表单按钮 -->
          <template v-if="showQueryButton">
            <el-button type="primary" :loading="loading" @click="doQuery(true)">查询</el-button>
            <el-button @click="$emit('update:query', {})">重置</el-button>
          </template>

          <!-- 按钮插槽 -->
          <slot name="btns" />
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 数据列表 -->
    <el-table
      ref="table"
      v-loading="loading"
      class="data-list"
      small="small"
      border
      :data="list"
      @selection-change="selected = $event"
    >
      <!-- 勾选列 -->
      <el-table-column v-if="selection" type="selection" width="40" fixed />

      <!-- 表格项插槽 -->
      <slot name="table" />
    </el-table>

    <!-- 分页 -->
    <div v-if="showPagination" class="pagination">
      <el-pagination
        layout="total, sizes, prev, pager, next, jumper"
        :current-page="pagination.page"
        :page-size="pagination.pageSize"
        :total="pagination.total"
        :page-sizes="PAGE_SIZES"
        @current-change="pageChangeHandler"
        @size-change="pageSizeChangeHandler"
      />
    </div>
  </div>
</template>

<script>
import { isPlainObject } from 'lodash/lang'

const PAGE_SIZES = [10, 20, 50, 100]
// 分页字段名
const API_PAGE_KEY = 'page'
const API_PAGESIZE_KEY = 'limit'

export default {
  name: 'QueryList',

  props: {
    // 是否展示筛选面板
    showQueryPanel: {
      type: Boolean,
      default: true
    },

    // 是否展示表单按钮
    showQueryButton: {
      type: Boolean,
      default: true
    },

    // 是否支持勾选
    selection: {
      type: Boolean,
      default: false
    },

    // 是否展示分页
    showPagination: {
      type: Boolean,
      default: true
    },

    // 是否初始化后立即查询
    queryImmediate: {
      type: Boolean,
      default: true
    },

    // 筛选参数对象
    query: {
      type: Object,
      default() {
        return {}
      }
    },

    // 查询请求方法
    queryService: {
      type: Function
    },

    /**
     * 请求适配方法
     * @param {object} postData 请求提交的数据
     * @returns {object} 适配后的数据，用于请求提交
     */
    requestAdaptor: {
      type: Function
    },

    /**
     * 响应适配方法
     * @param {object} data 响应的数据，包含列表数据、分页数据
     * @returns {object} 适配后的数据
     */
    responseAdaptor: {
      type: Function
    }
  },

  data() {
    return {
      // 列表数据
      list: [],
      // 选中项
      selected: [],

      // 分页对象
      pagination: {
        page: 1,
        pageSize: PAGE_SIZES[0],
        total: 0
      },

      // 加载状态
      loading: false
    }
  },

  computed: {
    PAGE_SIZES() {
      return PAGE_SIZES
    },

    queryObject() {
      return isPlainObject(this.query) ? this.query : {}
    }
  },

  mounted() {
    if (this.queryImmediate) {
      this.doQuery()
    }
  },

  methods: {
    /**
     * 页码变化处理方法
     */
    pageChangeHandler(page) {
      this.$set(this.pagination, 'page', page || 1)
      this.doQuery()
    },
    /**
     * 每页条数变化处理方法
     */
    pageSizeChangeHandler(pageSize) {
      this.$set(this.pagination, 'pageSize', pageSize || this.PAGE_SIZES[0])
      this.doQuery()
    },

    /**
     * 查询
     * @param {boolean} reset 是否复位页码
     */
    async doQuery(reset = false) {
      if (this.loading) return
      if (typeof this.queryService !== 'function') return

      // 准备提交的数据
      const pagination = reset === true ? {
        [API_PAGE_KEY]: 1,
        [API_PAGESIZE_KEY]: PAGE_SIZES[0]
      } : {
        [API_PAGE_KEY]: this.pagination.page,
        [API_PAGESIZE_KEY]: this.pagination.pageSize
      }

      let postData = { ...this.queryObject, ...pagination }
      // 提交数据适配
      if (typeof this.requestAdaptor === 'function') {
        postData = await this.requestAdaptor(postData)
        !isPlainObject(postData) && (postData = {})
      }

      this.loading = true

      try {
        // 发送请求
        let [result] = await this.queryService(postData)

        // 响应数据适配
        if (typeof this.responseAdaptor === 'function') {
          result = await this.responseAdaptor(result)
        }
        !isPlainObject(result) && (result = {})

        // 更新数据
        const { data, count } = result
        Array.isArray(data) && (this.list = data)
        reset && this.$set(this.pagination, 'page', pagination[API_PAGE_KEY])
        reset && this.$set(this.pagination, 'pageSize', pagination[API_PAGESIZE_KEY])
        count >= 0 && this.$set(this.pagination, 'total', count)
      } finally {
        this.loading = false
      }
    },

    /**
     * 获取勾选数据
     */
    getSelectedRows() {
      return this.selected
    },
    /**
     * 清空勾选数据
     */
    clearSelectedRows() {
      // 清空勾选数据
      this.selected = []

      // 调用方法，清空 el-table 组件勾选
      if (this.$refs.table) {
        this.$refs.table.clearSelection()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.query-panel {
  margin-bottom: 20px;
}

.query-form {
  margin-bottom: -18px;
}

.data-list {
  width: 100%;

  ::v-deep .el-table__empty-text {
    line-height: 300px;
  }
}

.pagination {
  margin-top: 10px;
}
</style>
